<template>
  <a-spin tip="请求发送中..." :spinning="sending">
    <div class="basic" style="overflow: hidden;">
      <a-layout style="width: 100%;">
        <a-layout-header style="background-color: #fff;">
          <a-row>
            <a-col :span="3">
              <a-input v-model:value="interfaceData.name" :bordered="false" placeholder="未命名"/>
            </a-col>
            <a-col :span="3">
              <a-checkbox
                  v-model:checked="isLocal"
                  size="small"
                  @click="isLocal = !isLocal">
                本地调试
              </a-checkbox>
            </a-col>
            <a-col :span="2" :offset="1">
              <a-space>
                <a-tag :bordered="false" style="font-size: 16px;" color="blue" title="点击修改接口前缀">
                  <a @click="changeUrl.changed = true" style="display: inline-block; padding: 5px 3px;">接口前缀</a>
                </a-tag>
              </a-space>
            </a-col>
          </a-row>
        </a-layout-header>
        <a-layout-content style="background-color: #fff; height : calc(100vh - 120px) ">
          <div class="info" style="padding: 0 25px">
            <a-row
                :gutter="3"
                justify="space-between"
                style="margin: 10px -2.5px"
            >
              <a-col :span="3" style="text-align: left;">
                <a-select
                    ref="select"
                    v-model:value="interfaceData.method"
                    style="width: 60%;"
                    :options="methods"
                ></a-select>
              </a-col>
              <a-col :span="14" style="text-align: left;">
                <a-input
                    v-model:value="interfaceData.url"
                    placeholder="路径接口，以'/'开头"
                    clearable
                    @change="validateInput"
                />
              </a-col>
              <a-col :span="7">
                <div style="min-width: 290px">
                  <a-button
                      type="primary"
                      plain
                      @click="sendRequest"
                      style="margin-top: 0; margin-right: 10px;"
                  >发送请求
                  </a-button>
                  <a-button
                      type="primary"
                      @click="saveInterface"
                      style="margin-top: 0"
                  >保存接口
                  </a-button>
                  <a-badge
                      v-if="isNotSave"
                      is-dot
                      class="item"
                      style="margin-left: -12px; margin-top: -20px"
                  />
                </div>
              </a-col>
            </a-row>
            <a-row>
              <a-col>
              <span style="color: #7e8186; padding-left: 25px;">
                实际发送请求地址: {{ realRequestPath }}
              </span>
              </a-col>
            </a-row>
          </div>
          <a-tabs class="interface-tabs" v-model="activeName" style="padding: 0 25px">
            <a-tab-pane key="Params" tab="Param" style="text-align: left;">
              <span>Query参数</span>
              <a-empty
                  v-if="interfaceData.requestParams.query.length <= 0"
                  :image-style="{height: '60px',}">
                <template #description>
                  <a-button @click="addParamsQuery">点击添加Query参数</a-button>
                </template>
              </a-empty>
              <div v-else>
                <div class="opera" style="display: flex; justify-content: flex-end; margin-bottom: 10px;">
                  <a-space>
                    <a-button type="primary" @click="addParamsQuery"> + 添加一条参数</a-button>
                    <a-button danger @click="deleteParamsQuery" :disabled="!hasQuerySelected"> - 删除所选参数</a-button>
                  </a-space>
                </div>
                <a-table :columns="params" :data-source="interfaceData.requestParams.query"
                         :row-selection="{ selectedQueryRowKeys: stateQuery.selectedQueryRowKeys, onChange: onQuerySelectChange }"
                         :rowKey="(record,index)=>{return index}"
                         :pagination="false">
                  <template #headerCell="{ column }">
                    <template v-if="column.key === 'name'">
                  <span>
                    {{ column.name }}
                  </span>
                    </template>
                  </template>
                  <template #bodyCell="{ column, record }">
                    <template v-if="column.key === 'name'">
                      <a-input v-model:value="record.name" @change="matchParams"/>
                    </template>
                    <template v-else-if="column.key === 'val'">
                      <a-input v-model:value="record.val" @change="matchParams"/>
                    </template>
                    <template v-else-if="column.key === 'type'">
                      <a-select v-model:value="record.type" placeholder="请选择" style="width: 120px;">
                        <a-select-option label="string" value="string"/>
                        <a-select-option label="integer" value="integer"/>
                        <a-select-option label="number" value="number"/>
                      </a-select>
                    </template>
                    <template v-else-if="column.key === 'required'" style="display: flex;justify-content: space-around;">
                      <a-checkbox v-model:checked="record.required"/>
                    </template>
                    <template v-else-if="column.key === 'description'">
                      <a-input v-model:value="record.description"/>
                    </template>
                  </template>
                </a-table>
              </div>
              <a-divider/>
              <span style="display: block; margin-top: 20px">Path参数</span>
              <a-empty
                  v-if="interfaceData.requestParams.path.length <= 0"
                  :image-style="{height: '60px',}">
                <template #description>
                  自动识别形如 {path} 的路径参数
                </template>
              </a-empty>
              <a-table v-else :columns="paths" :data-source="interfaceData.requestParams.path"
                       :pagination="false" bordered>
                <template #headerCell="{ column }">
                  <template v-if="column.key === 'name'">
                  <span>
                    {{ column.name }}
                  </span>
                  </template>
                </template>
                <template #bodyCell="{ column, record }">
                  <template v-if="column.key === 'name'">
                    <a-tooltip>
                      <a-input v-model:value="record.name" disabled title="请在请求路径修改">
                        {{ record.name }}
                      </a-input>
                    </a-tooltip>
                  </template>
                  <template v-if="column.key === 'val'">
                    <a-input v-model:value="record.val" style="width: 250px; min-width: 150px" @change="matchParams"/>
                  </template>
                  <template v-else-if="column.key === 'description'">
                    <a-input v-model:value="record.description"/>
                  </template>
                  <template v-if="column.key === 'type'">
                    <a-alert :message="record.type" type="info" style="width: 250px; min-width: 150px"
                             @change="matchParams"/>
                  </template>
                </template>
              </a-table>
            </a-tab-pane>
            <a-tab-pane key="Body" tab="Body">
              <a-alert message="目前仅支持JOSN格式的请求体" type="warning"/>
              <!--JSON输入框-->
              <JsonEditorVue
                  v-model="interfaceData.requestBody.content[0]"
                  mode="text"
                  :main-menu-bar="false"
                  :status-bar="false"
                  :ask-to-format="true"
                  style="text-align: left;"
              />
            </a-tab-pane>
            <a-tab-pane key="Header" tab="Header">
              <a-empty
                  v-if="interfaceData.requestHeaders.length <= 0"
                  :image-style="{height: '60px',}">
                <template #description>
                  <a-button @click="addHeader">点击添加请求头</a-button>
                </template>
              </a-empty>
              <div v-else>
                <div class="opera" style="display: flex; justify-content: flex-end; margin-bottom: 10px;">
                  <a-space>
                    <a-button type="primary" @click="addHeader"> + 添加请求头</a-button>
                    <a-button danger @click="deleteHeader" :disabled="!hasHeaderSelected"> - 删除所选请求头</a-button>
                  </a-space>
                </div>
                <a-table :columns="params" :data-source="interfaceData.requestHeaders"
                         :rowKey="(record,index)=>{return index}"
                         :row-selection="{ selectedHeaderRowKeys: stateHeader.selectedHeaderRowKeys, onChange: onHeaderSelectChange }"
                         :pagination="false">
                  <template #headerCell="{ column }">
                    <template v-if="column.key === 'name'">
                  <span>
                    {{ column.name }}
                  </span>
                    </template>
                  </template>
                  <template #bodyCell="{ column, record }">
                    <template v-if="column.key === 'name'">
                      <a-auto-complete
                          v-model:value="record.name"
                          :options="options"
                          style="width: 200px"
                          :filter-option="filterOption"
                      />
                    </template>
                    <template v-else-if="column.key === 'val'">
                      <a-input v-model:value="record.val" @change="matchParams"/>
                    </template>
                    <template v-else-if="column.key === 'type'">
                      <a-select v-model:value="record.type" placeholder="请选择" style="width: 120px;">
                        <a-select-option label="string" value="string"/>
                        <a-select-option label="integer" value="integer"/>
                        <a-select-option label="number" value="number"/>
                        <a-select-option label="array" value="array"/>
                      </a-select>
                    </template>
                    <template v-else-if="column.key === 'required'" style="display: flex;justify-content: space-around;">
                      <a-checkbox v-model:checked="record.required"/>
                    </template>
                    <template v-else-if="column.key === 'description'">
                      <a-input v-model:value="record.description"/>
                    </template>
                  </template>
                </a-table>
              </div>

            </a-tab-pane>
            <a-tab-pane key="desc" tab="接口描述">
              <a-textarea :rows="8">{{ interfaceData.description }}</a-textarea>
            </a-tab-pane>
            <a-tab-pane key="Response" tab="返回数据">
              <JsonEditorVue
                  v-model="interfaceData.responseData.content[0]"
                  mode="text"
                  :main-menu-bar="false"
                  :status-bar="false"
                  :ask-to-format="true"
                  style="text-align: left;"
              />
            </a-tab-pane>
          </a-tabs>
        </a-layout-content>
        <a-layout-footer style="background-color: #fff; padding: 0;">
          <a-alert type="info" message="返回响应" style="display: flex; margin-bottom: 10px; width: 100px;"/>
          <JsonEditorVue
              v-if="realResponse"
              v-model="realResponse"
              :main-menu-bar="false"
              :status-bar="false"
              :read-only="true"
              style="margin: 0 20px"
          />
          <p style="margin: 0 10px" v-else>点击"发送请求"按钮获取返回结果</p>
        </a-layout-footer>
      </a-layout>
    </div>
  </a-spin>

  <a-modal v-model:open="changeUrl.changed" width="600px" destroy-on-close="destroy-on-close"
           cancel-text="取消" ok-text="确认"
           @ok="modifyBaseUrl"
           @cancel="baseUrl = tempUrl"
  >
    <div style="margin: 20px 0;">
      <h3>接口前缀</h3>
    </div>
    <a-input v-model:value="baseUrl"/>
  </a-modal>
</template>

<script setup lang="ts">
import {useRoute} from "vue-router";
import {computed, reactive, ref} from "vue";
import {message, SelectProps} from "ant-design-vue";
import JsonEditorVue from 'json-editor-vue';
import "vanilla-jsoneditor/themes/jse-theme-dark.css";
import axios from "@/axios";
import Axios from 'axios'
import router from "@/router";

const route = useRoute();
const isNotSave = ref(false);
let changeUrl = ref({
  changed: false,
  info: '修改',
});

const modifyBaseUrl = () => {

  baseUrl.value = baseUrl.value.trim();
  const pattern = /^(https?:\/\/)(((?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,6}|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5})|localhost:\d{1,5})$/;
  if (pattern.test(baseUrl.value)) {
    changeUrl.value.changed = false;
    tempUrl = baseUrl.value;
    return;
  }
  baseUrl.value = tempUrl;
  message.warn("请求前缀格式错误")
}
// 请求前缀
const baseUrl = ref('http://localhost:8080')
let tempUrl = baseUrl.value;
const programId = route.params.id;
// 响应结果
const realResponse = ref('');
const isLocal = ref(true);
// 响应加载
const sending = ref(false);
// tab
const activeName = ref('Param')
const interfaceData = ref({
  name: '',
  url: '/',
  method: 'GET',
  requestHeaders: [],
  requestBody: {
    contentType: "application/json",
    content: [],
  },
  description: '',
  responseData: {
    contentType: "application/json",
    content: [],
  },
  requestParams: {
    path: [],
    query: [],
  },
  programId: route.params.id,
  catalogId: route.query.catalogId
})

// query参数列
const params = [
  {
    name: '参数名',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: '参数值',
    dataIndex: 'val',
    key: 'val',
  },
  {
    title: '类型',
    dataIndex: 'type',
    key: 'type',
  },
  {
    title: '是否必须',
    key: 'required',
    dataIndex: 'required',
  },
  {
    title: '参数说明',
    key: 'description',
    dataIndex: 'description'
  },
];

const paths = [
  {
    name: '参数名',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: '参数值',
    dataIndex: 'val',
    key: 'val',
  },
  {
    title: '参数说明',
    key: 'description',
    dataIndex: 'description'
  },
  {
    title: '类型',
    dataIndex: 'type',
    key: 'type',
  },
]

const methods = ref<SelectProps['options']>([
  {
    value: 'GET',
    label: 'GET',
  },
  {
    value: 'POST',
    label: 'POST',
  },
  {
    value: 'DELETE',
    label: 'DELETE',
  },
  {
    value: 'PUT',
    label: 'PUT',
  },
]);

// 请求头
const options = ref([
  {value: 'Accept'},
  {value: 'Authorization'},
  {value: 'Content-Type'},
  {value: 'User-Agent'},
]);

const stateQuery = reactive<{
  selectedQueryRowKeys: [];
  loading: boolean;
}>({
  selectedQueryRowKeys: [], // Check here to configure the default column
  loading: false,
});
const hasQuerySelected = computed(() => stateQuery.selectedQueryRowKeys.length > 0);
const onQuerySelectChange = (selectedQueryRowKeys) => {
  console.log(selectedQueryRowKeys)
  stateQuery.selectedQueryRowKeys = selectedQueryRowKeys;
};

const stateHeader = reactive<{
  selectedHeaderRowKeys: [];
  loading: boolean;
}>({
  selectedHeaderRowKeys: [], // Check here to configure the default column
  loading: false,
});
const hasHeaderSelected = computed(() => stateHeader.selectedHeaderRowKeys.length > 0);
const onHeaderSelectChange = (selectedHeaderRowKeys) => {
  stateHeader.selectedHeaderRowKeys = selectedHeaderRowKeys;
};
// 以下是方法
// 禁止手动输入query参数
const validateInput = () => {
  // 检查输入文本中是否包含 '?'
  if (interfaceData.value.url.includes('?')) {
    // 如果包含 '?'，则移除这个字符并更新输入框的值
    interfaceData.value.url = interfaceData.value.url.replace(/[?]/g, '');
    message.warn("query参数请在下方添加")
  } else {
    matchParams();
  }
}

// const realRequestPath = computed(() => {
//   // 匹配path参数,即{}中的参数
//   const pathParams = interfaceData.value.url.match(/{\w+}/g);
//   let path = interfaceData.value.url;
//   if (pathParams) {
//     pathParams.forEach((item) => {
//       const pathParam = interfaceData.value.requestParams.path.find(
//           (path) => path.name === item.slice(1, -1)
//       );
//       // 如果pathParam不存在，则跳过这一轮
//       if (!pathParam) {
//         return;
//       }
//       const pathParamExample = pathParam.val || "{" + pathParam.name + "}";
//       path = path.replace(item, pathParamExample);
//     });
//   }
//   // 匹配query参数,即?后的参数
//   const queryParams = interfaceData.value.requestParams.query;
//   if (queryParams) {
//     let query = "?";
//     queryParams.forEach((item) => {
//       if (item.required) {
//         query += item.name + "=" + item.val + "&";
//       }
//     });
//     path += query.slice(0, -1);
//   }
//   // if (isLocal.value) {
//   //   return baseUrl.value + '/local' + path;
//   // } else {
//   // }
//   return baseUrl.value + path;
// });

const realRequestPath = computed(() => {
  return baseUrl.value + url.value;
});

const url = computed(() => {
  // 匹配path参数,即{}中的参数
  const pathParams = interfaceData.value.url.match(/{\w+}/g);
  let path = interfaceData.value.url;
  if (pathParams) {
    pathParams.forEach((item) => {
      const pathParam = interfaceData.value.requestParams.path.find(
          (path) => path.name === item.slice(1, -1)
      );
      // 如果pathParam不存在，则跳过这一轮
      if (!pathParam) {
        return;
      }
      const pathParamExample = pathParam.val || "{" + pathParam.name + "}";
      path = path.replace(item, pathParamExample);
    });
  }
  // 匹配query参数,即?后的参数
  const queryParams = interfaceData.value.requestParams.query;
  if (queryParams) {
    let query = "?";
    queryParams.forEach((item) => {
      if (item.required) {
        query += item.name + "=" + item.val + "&";
      }
    });
    path += query.slice(0, -1);
  }
  return path;
})

const sendRequest = () => {
  if (!checkInterfaceData()) {
    return;
  }
  sending.value = true;
  if (!isLocal.value) {
    sendRequestByBackend();
  } else {
    sendRequestFront();
  }
  sending.value = false;
}

const sendRequestFront = () => {
  let body = {};
  if (interfaceData.value.requestBody.contentType === "application/json") {
    // 如果interfaceData.value.requestBody.content[0]是string，则转换为json
    if (typeof interfaceData.value.requestBody.content[0] === "string") {
      if (interfaceData.value.requestBody.content[0] === "") {
        interfaceData.value.requestBody.content[0] = {};
      } else {
        try {
          interfaceData.value.requestBody.content[0] = JSON.parse(
              interfaceData.value.requestBody.content[0]
          );
        } catch (error) {
          message.error("json格式错误");
          return;
        }
      }
    }
    body = interfaceData.value.requestBody.content[0];
  } else {
    body = interfaceData.value.requestBody.content;
  }
  console.log("发送的" + JSON.stringify(body));
  Axios({
    method: interfaceData.value.method,
    url: '/local' + url.value,
    // 将headers转换为请求的headers
    headers: interfaceData.value.requestHeaders.reduce((pre, cur) => {
      pre[cur.name] = cur.val;
      return pre;
    }, {}),
    params: interfaceData.value.requestParams.query.reduce((pre, cur) => {
      pre[cur.name] = cur.val;
      return pre;
    }, {}),
    // 将body转换为请求的body
    data: body,
  }).then((res) => {
        console.log(res);
        realResponse.value = res.data;
        message.success("发送请求成功");
      })
      .catch((err) => {
        realResponse.value = err;
        console.log(err);
      });
};

// 后端代理请求
const sendRequestByBackend = () => {

  const newInterfaceData = {
    url: realRequestPath.value,
    method: interfaceData.value.method,
    requestHeaders: JSON.stringify(interfaceData.value.requestHeaders, null, 2),
    requestBody: JSON.stringify(interfaceData.value.requestBody, null, 2),
  };

  axios.post('/api/send', newInterfaceData).then((response) => {
    realResponse.value = response.data;
    message.success("请求发送成功")
  })
}

const saveInterface = () => {
  if (!checkInterfaceData()) {
    return;
  }
  const newInterfaceData = {
    ...interfaceData.value,
    requestHeaders: JSON.stringify(
        interfaceData.value.requestHeaders,
        null,
        2
    ),
    requestParams: JSON.stringify(interfaceData.value.requestParams, null, 2),
    requestBody: JSON.stringify(interfaceData.value.requestBody, null, 2),
    responseData: JSON.stringify(interfaceData.value.responseData, null, 2),
  };

  axios.post(`/api/${interfaceData.value.programId}`, newInterfaceData).then((response) => {
    message.success(response.message)
    // 跳转至接口页面
    router.push({
      path: `/program/api/show/${programId}`,
      query: {
        apiId: response.data.id
      }
    })
  })
  console.log(newInterfaceData);
}
const checkInterfaceData = () => {
  // if (!interfaceData.value.url) {
  //   message.error("接口路径不能为空");
  //   return false;
  // }
  if (!interfaceData.value.method) {
    message.error("接口方法不能为空");
    return false;
  }
  if (interfaceData.value.requestBody.contentType === "application/json") {
    if (typeof interfaceData.value.requestBody.content[0] === "string") {
      if (interfaceData.value.requestBody.content[0] === "") {
        interfaceData.value.requestBody.content[0] = {};
      } else {
        try {
          interfaceData.value.requestBody.content[0] = JSON.parse(
              interfaceData.value.requestBody.content[0]
          );
        } catch (error) {
          message.error("json格式错误");
          return false;
        }
      }
    }
  }
  // 检查并处理
  if (interfaceData.value.responseData.contentType === "application/json") {
    if (typeof interfaceData.value.responseData.content[0] === "string") {
      if (interfaceData.value.responseData.content[0] === "") {
        interfaceData.value.responseData.content[0] = {};
      } else {
        try {
          interfaceData.value.responseData.content[0] = JSON.parse(
              interfaceData.value.responseData.content[0]
          );
        } catch (error) {
          message.error("json格式错误");
          return false;
        }
      }
    }
  }
  return true;
};

const matchParams = () => {
  // 匹配path参数,即{}中的参数
  const pathParams = interfaceData.value.url.match(/{\w+}/g);
  if (pathParams) {
    // 如果interfaceData.value.requestParams.path存在但是没有这个pathParams，则删除
    interfaceData.value.requestParams.path.forEach((item, index) => {
      const pathParam = pathParams.find(
          (path) => path.slice(1, -1) === item.name
      );
      if (!pathParam) {
        interfaceData.value.requestParams.path.splice(index, 1);
      }
    });
    // 如果interfaceData.value.requestParams.path存在这个pathParams，则不变
    pathParams.forEach((item) => {
      const pathParam = interfaceData.value.requestParams.path.find(
          (path) => path.name === item.slice(1, -1)
      );
      if (!pathParam) {
        interfaceData.value.requestParams.path.push({
          name: item.slice(1, -1),
          description: "",
          required: true,
          val: "",
          type: "string",
        });
      }
    });
  } else {
    interfaceData.value.requestParams.path = [];
  }
}

// 添加路径参数
const addParamsQuery = () => {
  if (
      // 如果上一个query参数没有填写完整，则不允许添加新的query参数
      interfaceData.value.requestParams.query.length === 0 ||
      interfaceData.value.requestParams.query[
      interfaceData.value.requestParams.query.length - 1
          ].name
  ) {
    interfaceData.value.requestParams.query.push({
      name: "",
      val: "",
      type: "string",
      description: "",
      required: true,
    });
  } else {
    message.error("请先填写完整上一个query参数");
  }
};
const deleteParamsQuery = () => {
  stateQuery.selectedQueryRowKeys.forEach((index) => {
    interfaceData.value.requestParams.query.splice(index, 1);
  })
};

const addHeader = () => {
  if (
      // 如果上一个headers参数没有填写完整，则不允许添加新的headers参数
      interfaceData.value.requestHeaders.length == 0 ||
      interfaceData.value.requestHeaders[
      interfaceData.value.requestHeaders.length - 1
          ].name
  ) {
    interfaceData.value.requestHeaders.push({
      name: "",
      val: "",
      type: "string",
      description: "",
      required: true,
    });
  } else {
    message.error("请先填写完整上一个Header参数");
  }
};
const deleteHeader = () => {
  stateHeader.selectedHeaderRowKeys.forEach((index) => {
    interfaceData.value.requestHeaders.splice(index, 1);
  })
};

// 不区分大小写
const filterOption = (input: string, option) => {
  return option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0;
};
</script>

<style scoped lang="less">

.basic {
  width: 100%;
  height: 100%;
  display: flex;
  overflow-x: hidden;

  .ant-layout {
    display: flex;

  }
}
</style>